/****************************************************************
 *  * *Process the diff os interface
 *  * *
 *  * *file name:mct_system.h
 *  * *
 *  * *Copyright (C)2012 Cisco webex.
 *  * *All rights reserved
 *  * *
 *  * *Author:zhenye
 *  * *Date  :2013-03-06
 *  * *
 *  * ****************************************************************/

#ifndef _MCT_SYSTEM_H_
#define _MCT_SYSTEM_H_

/* include header file for linux poll */
#ifndef WIN32
#include <poll.h>
#include <sys/poll.h>
#include <sys/epoll.h>
#endif

#include <assert.h>

/* include ACE header file */
#include "ace/ACE.h"
#include "ace/OS.h"

#ifdef  __cplusplus
extern "C"{
#endif

/* compile  option */
#if defined(WIN32)
    #if defined(MCT_EXPORTS_DLL)
        #define MCT_EXPORT  __declspec( dllexport )
    #else
        #if defined(MCT_STATIC_LIB)
            #define MCT_EXPORT
        #else
            #define MCT_EXPORT  __declspec( dllimport )
        #endif
    #endif
#else
    #define MCT_EXPORT
#endif

/* define function export format */
#ifdef WIN32
    #define MCT_STDCALL         __stdcall
#else
    #define MCT_STDCALL         __attribute__((stdcall))
#endif

/* simple type define */

/** 8 bit sign number type*/
#ifndef CHAR
typedef char CHAR;
#endif

/** 8 bit unsign number type*/
#ifndef UCHAR
typedef unsigned char UCHAR;
#endif

/** 16 bit sign number type*/
#ifndef SHORT
typedef short SHORT;
#endif

/** 16 bit unsign number type*/
#ifndef USHORT
typedef unsigned short USHORT;
#endif

/** 32 bit sign number type*/
#ifndef LONG
typedef long LONG;
#endif

/** 32 bit unsign number type*/
#ifndef ULONG
typedef unsigned long ULONG;
#endif

/** 64 bit sign number type*/
#ifndef DLONG
#if defined (_MSC_VER)
typedef __int64 DLONG;
#else
typedef long long DLONG;
#endif
#endif

/** 64 bit unsign number type*/
#ifndef DULONG
#if defined (_MSC_VER)
typedef unsigned __int64 DULONG;
#else
typedef unsigned long long DULONG;
#endif
#endif

/** double type*/
#ifndef DOUBLE
typedef double DOUBLE;
#endif

/** float type*/
#ifndef FLOAT
typedef float FLOAT;
#endif

/** bool type*/
typedef bool  BOOL_T;

/** size_t type*/
#ifndef SIZE_T
typedef unsigned long SIZE_T;
#endif

/** void type */
#define VOID           void

/** define bool value */
#define BOOL_TRUE                       ((BOOL_T) 1)
#define BOOL_FALSE                      ((BOOL_T) 0)

#ifndef NULL
#define NULL (void *)0
#endif

#define MCT_UNUSED_ARG(arg)      ((VOID) (arg))

#define MCT_PROCESS_NAME_LEN         64
#define MCT_PROCESS_LOCK_BUFF_LEN        128

/** define pid type */
typedef pid_t                   MCT_PID_S;

/** define process exit code type */
typedef ACE_exitcode       MCT_EXITCODE_S;

/** define signal action type */
typedef ACE_SIGACTION   MCT_SIGACTION_S;

/** define signal info type */
typedef siginfo_t             MCT_SIGINFO_S;

/** define signal set type */
typedef sigset_t              MCT_SIGSET_S;

/** define signal handler function pointer */
typedef ACE_SignalHandler MCT_SIGNAL_HANDLER_PF;

/** define signal handler for MCT_SIGACTION_S (just for linux system) */
#ifndef WIN32
typedef ACE_SIGNAL_C_FUNC MCT_SIGNAL_HANDLER_WITH_SIGINFO_PF;
#endif

/** wait process terminate option */
#define MCT_WNOHANG                 WNOHANG
#ifdef WIN32
#define MCT_WUNTRACED              0
#define MCT_WCONTINUED            0
#else
#define MCT_WUNTRACED              WUNTRACED
#define MCT_WCONTINUED             WCONTINUED
#endif

/** check process status */
#define MCT_WIFEXITED(status)            (WIFEXITED(status))
#define MCT_WIFSIGNALED(status)        (WIFSIGNALED(status))
#define MCT_WEXITSTATUS(status)        (WEXITSTATUS(status))
#define MCT_WTERMSIG(status)             (WTERMSIG(status))
#define MCT_WIFSTOPPED(status)          (WIFSTOPPED(status))
#define MCT_WSTOPSIG(status)              (WSTOPSIG(status))
#define MCT_WIFCONTINUED(status)       (WIFCONTINUED(status))

/** mac addr min length */
#define MIN_MAC_ADDR_LEN                12

/**define common invalid handle */
#define MCT_INVALID_HANDLE             ACE_INVALID_HANDLE

/** process flag max length */
#define MCT_MAX_PROCESS_NAME_LEN         64
#define MCT_PROCESS_LOCK_BUFF_LEN        128

/** prefix for process lock, Windows use kerne objectl, Linux use file system */
#ifdef WIN32
#define MCT_PROCESS_LOCK_PREFIX          "Global\\mct."
#else
#define MCT_PROCESS_LOCK_PREFIX          "/var/run/mct."
#endif

/** define file mode type */
typedef mode_t                          MCT_MODE_S;

/* define linux operate for mode_t type */
#ifndef WIN32
/** set user ID on execution */
#define MCT_S_ISUID                    S_ISUID
/** set group ID on execution */
#define MCT_S_ISGID                    S_ISGID
/** sticky bit */
#define MCT_S_ISVTX                    S_ISVTX
/** read by owner */
#define MCT_S_IRUSR                    S_IRUSR
/** write by owner */
#define MCT_S_IWUSR                   S_IWUSR
/** execute/search by owner */
#define MCT_S_IXUSR                    S_IXUSR
/** read by group */
#define MCT_S_IRGRP                    S_IRGRP
/** write by group */
#define MCT_S_IWGRP                   S_IWGRP
/** execute/search by group */
#define MCT_S_IXGRP                    S_IXGRP
/** read by others */
#define MCT_S_IROTH                    S_IROTH
/** write by others */
#define MCT_S_IWOTH                   S_IWOTH
/** execute/search by others */
#define MCT_S_IXOTH                    S_IXOTH
#endif

/** define file operate offset */
typedef ACE_OFF_T                       MCT_OFF_S;
typedef ACE_LOFF_T                      MCT_LOFF_S;

/** define linux directory option */
#ifndef WIN32
    #ifndef O_DIRECT
    #define O_DIRECT                    (0x4000)
    #endif
#endif

/** define directory type */
typedef ACE_DIR                         MCT_DIR_S;
typedef ACE_DIRENT                    MCT_DIRENT_S;
typedef ACE_stat                        MCT_STAT_S;

/** define handle type */
typedef ACE_HANDLE                   MCT_HANDLE;

typedef sockaddr                        MCT_SOCKADDR_S;
typedef in_addr                          MCT_IN_ADDR_S;
typedef hostent                         MCT_HOSTENT_S;
typedef fd_set                           MCT_FD_SET_S;
typedef sockaddr_in                    MCT_SOCKADDR_IN_S;

#if !defined (INADDR_NONE)
#define INADDR_NONE ((ULONG) 0xffffffff)
#endif /* INADDR_NONE */


/** define poll type for OS not support poll that can  transform to select */
typedef struct tagMctPollFd
{
    int lFd;
    USHORT usEvents;
    USHORT usRevents;
}MCT_POLLFD_S;

#ifndef POLLIN
#define POLLIN                          (0x0001)
#endif

#ifndef POLLOUT
#define POLLOUT                         (0x0002)
#endif

#ifndef POLLERR
#define POLLERR                         (0x0004)
#endif

/** define select operate function */
#define MCT_SCANDIR_COMPARATOR_PF   ACE_SCANDIR_COMPARATOR
#define MCT_SCANDIR_SELECTOR_PF        ACE_SCANDIR_SELECTOR

/** define date and time type */
typedef time_t                          MCT_TIME_S;
typedef clockid_t                       MCT_CLOCKID_S;

#define MCT_CLOCK_REALTIME             0
#define MCT_CLOCK_MONOTONIC            1
#define MCT_CLOCK_PROCESS_CPUTIME_ID   2
#define MCT_CLOCK_THREAD_CPUTIME_ID    3

typedef struct tagMctTimeValue
{
    LONG lSec;
    LONG lUsec;
}MCT_TIME_VALUE_S;

typedef struct tagMctDateTime
{
    LONG lSec;
    LONG lMin;
    LONG lHour;
    LONG lMday;
    LONG lMon;
    /** years from 1900 to now */
    LONG lYear;
    /** values [0,6] */
    LONG lWday;
    /** values [0,365] */
    LONG lYday;
    /** summer ime: 0 if not; >0 if dst in effet; <0 if unknown */
    LONG lIsdst;
    /** glibc new add:seconds east of UTC. */
    LONG lGmtoff;
    /** glibc new add:timezone abbreviation. */
    const CHAR *pcZone;

}MCT_DATE_TIME_S;


typedef struct tagMctTimeZone
{
    /** Minutes west of GMT. */
    LONG  lMinutesWest;
    /** Nonzero if DST is ever in effect. */
    LONG  lDstTime;
}MCT_TIME_ZONE_S;

typedef struct tagMctTimeSpec
{
   MCT_TIME_S stSec;
    LONG lNsec;
} MCT_TIMESPEC_S;

/** define thread\ lock and synch type */
typedef ACE_thread_t                        MCT_THREAD_S;
typedef ACE_THR_FUNC                      MCT_THR_FUNC;
typedef ACE_THR_FUNC_RETURN          MCT_THR_FUNC_RETURN;

#ifdef WIN32
typedef ACE_mutex_t                            MCT_MUTEX_S;
#else
typedef ACE_recursive_thread_mutex_t    MCT_MUTEX_S;
#endif

typedef ACE_mutexattr_t                 MCT_MUTEXATTR_S;
typedef ACE_cond_t                        MCT_COND_S;

/** thread support operate in attribute */
#define MCT_THR_CANCEL_ENABLE                THR_CANCEL_ENABLE
#define MCT_THR_CANCEL_DISABLE               THR_CANCEL_DISABLE
#define MCT_THR_CANCEL_DEFERRED             THR_CANCEL_DEFERRED
#define MCT_THR_CANCEL_ASYNCHRONOUS    THR_CANCEL_ASYNCHRONOUS
#define MCT_THR_BOUND                               THR_BOUND
#define MCT_THR_NEW_LWP                           THR_NEW_LWP
#define MCT_THR_DETACHED                          THR_DETACHED
#define MCT_THR_JOINABLE                           THR_JOINABLE
#define MCT_THR_SUSPENDED                         THR_SUSPENDED
/** create daemon thread */
#define MCT_THR_DAEMON                              THR_DAEMON
/** control by fifo regular */
#define MCT_THR_SCHED_FIFO                        THR_SCHED_FIFO
/** control by priority regular */
#define MCT_THR_SCHED_RR                           THR_SCHED_RR
/** control by default regular */
#define MCT_THR_SCHED_DEFAULT                  THR_SCHED_DEFAULT
/** explicit control */
#define MCT_THR_EXPLICIT_SCHED                  THR_EXPLICIT_SCHED
/** control scope is system */
#define MCT_THR_SCOPE_SYSTEM                    THR_SCOPE_SYSTEM
/** control scope is process */
#define MCT_THR_SCOPE_PROCESS                   THR_SCOPE_PROCESS

/* default thread priority */
#define MCT_DEFAULT_THREAD_PRIORITY         ACE_DEFAULT_THREAD_PRIORITY

/** data compare function */
#define MCT_MIN(a, b)                  (ACE_MIN(a, b))
#define MCT_MAX(a, b)                  (ACE_MAX(a, b))
#define MCT_RANGE(a, b, c)           (ACE_RANGE(a, b, c))

/** handle of share lib */
typedef ACE_SHLIB_HANDLE             MCT_SHLIB_HANDLE;

/** network byte sequence */
#define MCT_HTONL(x)                   (MCT_htonl(x))
#define MCT_NTOHL(x)                   (MCT_ntohl(x))
#define MCT_HTONS(x)                   (MCT_htons(x))
#define MCT_NTOHS(x)                   (MCT_ntohs(x))
#define MCT_HTONLL(x)                  (MCT_htonll(x))
#define MCT_NTOHLL(x)                  (MCT_ntohll(x))

/** assert */
#define MCT_ASSERT(x)                  (assert(x))


#define  MCT_SYS_NMLN 257
typedef struct MCT_utsname
{
  CHAR sysname[MCT_SYS_NMLN];
  CHAR nodename[MCT_SYS_NMLN];
  CHAR release[MCT_SYS_NMLN];
  CHAR version[MCT_SYS_NMLN];
  CHAR machine[MCT_SYS_NMLN];
}MCT_UTSNAME_S;


#ifndef WIN32
typedef union tagMctEpollData {
     VOID *ptr;
     MCT_HANDLE fd;
     ULONG u32;
     DULONG u64;
}MCT_EPOLL_DATA_S;

#pragma pack(push, 1)

typedef struct tagMctEpollEvent
{
    ULONG events;            /* Epoll events */
    MCT_EPOLL_DATA_S data;  /* User data variable */
}MCT_EPOLL_EVENT_S;

#pragma pack(pop)

/** linux support epoll */
#define MCT_epoll_create                                 epoll_create
#define MCT_epoll_ctl(epfd, op, fd, event)           epoll_ctl(epfd, op, fd, (struct epoll_event *)(VOID *)(event))
#define MCT_epoll_wait(epfd, event, maxevents, timeout)  \
                        epoll_wait(epfd, (struct epoll_event *)(VOID *)(event), maxevents, timeout)
#endif

#define MCT_sscanf                     sscanf

/** define point for share lib function */
typedef VOID (*MCT_LIBMETHOD_PF)(VOID);


/** malloc memory
* param: ulLen              input the malloc memory size
* param: ulThreadId       input the thread-id of malloc memory
* param: szFileName       input the malloc file, suggest use __FILE__
* param: ulLine              input the malloc position, suggest use __LINE__
* return VOID* the malloc memory point, if failed return NULL
*/
MCT_EXPORT VOID *MCT_inmalloc(SIZE_T ulLen, ULONG ulThreadId, CHAR *szFileName, ULONG ulLine);

#define MCT_malloc(ulLen, ulThreadId) MCT_inmalloc((ulLen), (ulThreadId), __FILE__, __LINE__)

/** free memory
* param: ppBuf              input the address of memory point
* param: szFileName       input the malloc file, suggest use __FILE__
* param: ulLine              input the malloc position, suggest use __LINE__
* return VOID, it will set the memory point to NULL
*/
MCT_EXPORT VOID MCT_infree(VOID **ppBuf, CHAR *szFileName, ULONG ulLine);
#define MCT_free(ppBuf) MCT_infree((ppBuf), __FILE__, __LINE__)

/** memory compare
* param: pDestPtr          input the dst memory pointer
* param: pSrcPtr           input the source memory pointer
* param: ulLen              input compare memory len
* return LONG, 0 :the memory info same
                     >0 : pDestPtr info greater than pSrcPtr
                     <0 : pDestPtr info less than pSrcPtr
*/
MCT_EXPORT LONG MCT_memcmp(const VOID *pDestPtr, const VOID *pSrcPtr, SIZE_T ulLen);


/** memory copy
* param: pDestPtr          input the dst memory pointer
* param: pSrcPtr           input the source memory pointer
* param: ulLen              input copy memory len
* return VOID* a pointer to the pDestPtr
*/
MCT_EXPORT VOID *MCT_memcpy( VOID *pDestPtr, const VOID *pSrcPtr, SIZE_T ulLen);

/** memory set
* param: pToSet           input the set memory pointer
* param: lValue             input the memory set value
* param: ulLen              input set memory len
* return VOID* a pointer to the pToSet
*/
MCT_EXPORT VOID *MCT_memset(VOID *pToSet, LONG lValue, SIZE_T ulLen);

/** memory zero
* param: pToSetZero     input the zero memory pointer
* param: ulLen              input set memory len
* return VOID* a pointer to the pToSetZero
*/
MCT_EXPORT VOID *MCT_memzero(VOID *pToSetZero, SIZE_T ulLen);

/** string compare without case sensitive
* param: pcDest            input the dst string pointer
* param: pcSrc             input the source string pointer
* param: ulLen              input compare string len
* return LONG, 0 :the string is same
                     >0 : pcDest info greater than pcSrc
                     <0 : pcDest info less than pcSrc
*/
MCT_EXPORT LONG MCT_strncasecmp(const CHAR *pcDest, const CHAR *pcSrc, SIZE_T ulLen);

/** concatenate two strings
* param: pcDest            input the dst string pointer
* param: pcSrc             input the source string pointer
* param: ulLen              input source string length
* return CHAR* a pointer to the resulting string pcDest
*/
MCT_EXPORT CHAR *MCT_strncat(CHAR *pcDest, const CHAR *pcSrc, SIZE_T ulLen);

/** locate character first occurrence in string
* param: pcSrc             input the source string pointer
* param: cValue            input the match char
* param: ulLen              input the length need be find in source string
* return CHAR* a pointer to the first occurrence of the character cValue in the string pcSrc. if not match, return NULL
*/
MCT_EXPORT const CHAR *MCT_strnchr(const CHAR *pcStr, CHAR cValue, SIZE_T ulLen);

/** string compare in define length
* param: pcDest            input the dst string pointer
* param: pcSrc             input the source string pointer
* param: ulLen              input compare string len
* return LONG, 0 :the string is same
                     >0 : pcDest info greater than pcSrc
                     <0 : pcDest info less than pcSrc
*/
MCT_EXPORT LONG MCT_strncmp(const CHAR *pcDest, const CHAR *pcSrc, SIZE_T ulLen);

/** string compare
* param: pcDest            input the dst string pointer
* param: pcSrc             input the source string pointer
* return LONG, 0 :the string is same
                     >0 : pcDest info greater than pcSrc
                     <0 : pcDest info less than pcSrc
*/
MCT_EXPORT LONG MCT_strcmp(const CHAR *pcDest, const CHAR *pcSrc);

/** copy a string
* param: pcDest           input the dst string pointer
* param: pcSrc             input the source string pointer
* param: ulLen              input dst buffer max len
* return CHAR* a pointer to the pcDest
*/
MCT_EXPORT CHAR *MCT_strncpy(CHAR *pcDest, const CHAR *pcSrc, SIZE_T ulLen);

/** get string active length
* param: pcSrc             input the string pointer
* param: ulMaxlen          input string max len
* return SIZE_T the string active length
*/
MCT_EXPORT SIZE_T MCT_strnlen(const CHAR *pcStr, SIZE_T ulMaxlen);

/** get string active length
* param: pcSrc             input the string pointer
* return SIZE_T the string active length
*/
MCT_EXPORT SIZE_T MCT_strlen(const CHAR *pcStr);

/** locate sub-string first occurrence in string
* param: pcSrc             input the source string pointer
* param: pcSubStr        input the match sub-string
* param: ulLen              input length of sub-string
* return CHAR* a pointer to the first occurrence of the sub-string pcSubStr in the string pcSrc. if not match, return NULL
*/
MCT_EXPORT const CHAR *MCT_strnstr(const CHAR *pcStr, const CHAR *pcSubStr, SIZE_T ulLen);

/** locate character last occurrence in string
* param: pcSrc             input the source string pointer
* param: cValue            input the match char
* return CHAR* a pointer to the last occurrence of the character cValue in the string pcSrc. if not match, return NULL
*/
MCT_EXPORT const CHAR *MCT_strrchr(const CHAR *pcStr, CHAR cValue);

/**  convert letter to lower case
* param: lValue             input the need convert char
* return LONG the converted letter, or lValue if the conversion was not possible.
*/
MCT_EXPORT LONG MCT_tolower(LONG lValue);

/**  convert letter to upper case
* param: lValue             input the need convert char
* return LONG the converted letter, or lValue if the conversion was not possible.
*/
MCT_EXPORT LONG MCT_toupper(LONG lValue);

/** format string output to the buffer
* param: pcBuf             input the output buffer pointer
* param: ulMaxlen         input the max of buffer length
* param: pcFormat        input the output string format
* return LONG return the output string length and auto add terminate char('\0') at string end.
* if the output string length greater than ulMaxlen, the return value is ulMaxlen+1 and the position ulMaxlen-1 of output buffer be set erminate char('\0')
* note:the ulMaxlen must not greater than the pcBuf active length.
*/
MCT_EXPORT LONG MCT_snprintf(CHAR *pcBuf, SIZE_T ulMaxlen, const CHAR *pcFormat, ...);

/** parses a string into a sequence of tokens.
On the first call to strtok() the string to be parsed should be specified in str.
In each subsequent call that should parse the same string, str should be NULL.
* param: pcStr             input the need split source string pointer
* param: pcSep            input the delimited string
* param: ppcLast          a char * variable that is used internally by strtok_r() in order to maintain context between successive calls that parse the same string.
* return  CHAR * a pointer to the next token, or NULL if there are no more tokens.
*/
MCT_EXPORT CHAR *MCT_strtok_r(CHAR *pcStr, const CHAR *pcSep, CHAR **ppcLast);

/** locate character first occurrence in string
* param: pcSrc             input the source string pointer
* param: lValue             input the match char
* return CHAR* a pointer to the first occurrence of the character lValue in the string pcSrc. if not match, return NULL
*/
MCT_EXPORT const CHAR *MCT_strchr(const CHAR *pcStr, LONG lValue);

/** open the file whose name is the string pointed to by pcFilename and associates a stream with it
* param: pcFilename      input the string pointed to path of open file
* param: pcMode           input the mode string, such as "a"\"a+"\"r"\"r+"\"w"\"w+"
* return  FILE * a FILE pointer. Otherwise, NULL is returned and errno is set to indicate the error
*/
MCT_EXPORT FILE *MCT_fopen(const CHAR *pcFilename, const CHAR *pcMode);

/**
* close a file stream
* param: pFile      input the FILE pointer
* return LONG 0 for succeed. Otherwise, errno is set to indicate the error
*/
MCT_EXPORT LONG MCT_fclose(FILE *pFile);

/**
* examines the argument stream and returns its integer descriptor.
* param: pFile      input the FILE pointer
* return MCT_HANDLE convert handle descriptor
*/
MCT_EXPORT MCT_HANDLE MCT_fileno(FILE *pFile);

/** binary stream output
* param: pVoid      input pointer to the data buffer
* param: ulSize     input once write size
* param: ulItems   input write number of times
* param: pFile       input the FILE pointer
* return LONG the number of items successfully written. If an error occurs, or the end-of-file is reached, the return value is a short item count (or zero).
*/
MCT_EXPORT LONG MCT_fwrite(const VOID *pVoid, SIZE_T ulSize, SIZE_T ulItems, FILE *pFile);

/** binary stream input
* param: pVoid      input pointer to store the data buffer
* param: ulSize     input once read size
* param: ulItems   input read number of times
* param: pFile       input the FILE pointer
* return LONG the number of items successfully read. If an error occurs, or the end-of-file is reached, the return value is a short item count (or zero).
*/
MCT_EXPORT LONG MCT_fread(VOID *pVoid, SIZE_T ulSize, SIZE_T ulItems, FILE *pFile);

/** sets the file position indicator for the stream pointed to by stream
* param: pFile       input the FILE pointer
* param: lOffset    input move file position offset number
* param: lPtrPos    input move start position
* return LONG 0 is succeed. Otherwise, -1 is returned and errno is set to indicate the error.
*/
MCT_EXPORT LONG MCT_fseek(FILE *pFile, LONG lOffset, LONG lPtrPos);

/** forces a write of all user-space buffered data for the given output or update stream via the stream's underlying write function
* param: pFile       input the FILE pointer
* return LONG 0 is succeed. Otherwise, EOF is returned and errno is set to indicate the error.
*/
MCT_EXPORT LONG MCT_fflush(FILE *pFile);

/** reads the next character from stream
* param: pFile       input the FILE pointer
* return LONG as an unsigned char cast to an LONG, or EOF on end of file or error.
*/
MCT_EXPORT LONG MCT_fgetc(FILE *pFile);

/** reads in at most one less than size characters from stream and stores them into the buffer
* param: pBuf       input pointer to store the data buffer
* param: lSize       input read size
* param: pFile       input the FILE pointer
* return CHAR* a pointer to pBuf , and NULL on error or when end of file occurs while no characters have been read.
*/
MCT_EXPORT CHAR *MCT_fgets(CHAR *pBuf, LONG lSize, FILE *pFile);

/**
* write output to the given output stream
* param: pFile        input the FILE pointer
* param: pcFormat  input the format of output stream
* return LONG the number of characters output, if failerd return -1
*/
MCT_EXPORT LONG MCT_fprintf(FILE *pFile, const CHAR *pcFormat, ...);

/** write the character to stream
* param: lValue     input the write character
* param: pFile       input the FILE pointer
* return LONG as an unsigned char cast to an LONG, or EOF on error.
*/
MCT_EXPORT LONG MCT_fputc(const LONG lValue, FILE *pFile);

/** write in at most one less than size characters to stream from the buffer
* param: pBuf       input pointer to the data buffer
* param: pFile       input the FILE pointer
* return LONG a nonnegative number on success, or EOF on error.
*/
MCT_EXPORT LONG MCT_fputs(const CHAR *pcBuf, FILE *pFile);

/** obtains the current value of the file position indicator for the stream pointed to by stream
* param: pFile       input the FILE pointer
* return LONG the current offset. Otherwise, -1 is returned and errno is set to indicate the error.
*/
MCT_EXPORT LONG MCT_ftell(FILE *pFile);

/** renames a file, moving it between directories if required
* param: pcOldName       input the FILE old path string
* param: pcNewName      input the FILE new path string
* param: lFlags               input the FILE change mode, common default is -1
* return LONG  0 is means succeed; otherwise, -1 shall be returned, errno shall be set to indicate the error,
*/
MCT_EXPORT LONG MCT_rename(const CHAR *pcOldName, const CHAR *pcNewName, LONG lFlags);

/** create a file
* param: pcFilename       input the need creat FILE path string
* param: lMode              input the file mode if create a new file
* return MCT_HANDLE  the handle of create file, if failed return 0
*/
MCT_EXPORT MCT_HANDLE MCT_creat(const CHAR *pcFilename, LONG lMode);

/** synchronize changes to a file
* param: hHandle           input the handle of create file
* return LONG  0 is means succeed. Otherwise, -1 shall be returned and errno set to indicate the error
*/
MCT_EXPORT LONG MCT_fsync(MCT_HANDLE hHandle);

/** get file status
* param: hHandle           input the handle of create file
* param: pstStat           input the pointer to the store file status
* return LONG  0 is means succeed. Otherwise, -1 shall be returned and errno set to indicate the error
*/
MCT_EXPORT LONG MCT_fstat(MCT_HANDLE hHandle, MCT_STAT_S *pstStat);

/** get file status
* param: pcFile             input the pointer to file path string
* param: pstStat           input the pointer to the store file status
* return LONG  0 is means succeed. Otherwise, -1 shall be returned and errno set to indicate the error
*/
MCT_EXPORT LONG MCT_stat(const CHAR *pcFile, MCT_STAT_S *pstStat);

/** delete file
* param: pcPath            input the pointer to file path string
* return LONG  0 is means succeed. Otherwise, -1 shall be returned and errno set to indicate the error
*/
MCT_EXPORT LONG MCT_unlink(const CHAR *pcPath);

/** reposition read/write large-file offset
* param: hHandle           input the handle of create file
* param: stOffset          input move file position offset number
* param: lWhence          input move start position
* return MCT_LOFF_S  the reposition position. if returned -1 means failed and errno set to indicate the error
*/
MCT_EXPORT MCT_LOFF_S MCT_llseek(MCT_HANDLE hHandle, MCT_LOFF_S stOffset, LONG lWhence);

/** execute shell command
* param: pcStr             input the execute command
* return LONG
for linux:
if succeed return the shell command exit value
if call /bin/sh failed, return 127, other failed returned is -1 and exit code of the command will be WEXITSTATUS(status)
if pcStr is NULL, return non-zero
*/
MCT_EXPORT LONG MCT_system(const CHAR *pcStr);

/** open a sys dev file
* param: pcFilename       input the need creat FILE path string
* param: lMode              input the file mode for open
* param: stPerms           input the open privilege
* return MCT_HANDLE  a non-negative integer representing the lowest numbered unused file descriptor.
Otherwise, -1 shall be returned and errno set to indicate the error
*/
MCT_EXPORT MCT_HANDLE MCT_open(const CHAR *pcFilename, LONG lMode, MCT_MODE_S stPerms);

/** close a sys dev file
* param: hHandle       input the opened file handle
* return LONG  0 is means succeed. Otherwise, -1 shall be returned and errno set to indicate the error
*/
MCT_EXPORT LONG MCT_close(MCT_HANDLE hHandle);

/** read a sys dev file
* param: hHandle       input the opened file handle
* param: pBuf            input the pointer to the store data buffer
* param: ulLen           input the buffer length
* return LONG non-negative integer indicating the number of bytes actually read.
Otherwise, the functions shall return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_read(MCT_HANDLE hHandle, VOID *pBuf, SIZE_T ulLen);

/** write a sys dev file
* param: hHandle       input the opened file handle
* param: pBuf            input the pointer to the write data buffer
* param: ulLen           input the write data length
* return LONG non-negative integer indicating the number of bytes actually write.
Otherwise, the functions shall return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_write(MCT_HANDLE hHandle, const VOID *pBuf, SIZE_T ulByte);

/**  create a directory
* param: pcDirName      input the pointer to the new dir path
* param: usMode          input the mode of this new dir
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_mkdir(const CHAR *pcDirName, USHORT usMode);

/**  open a directory
* param: pcDirName      input the pointer to the open dir path
* param: usMode          input the mode of this new dir
* return MCT_DIR_S * a pointer to the open dir stream, if failed return NULL and errno is set appropriately.
*/
MCT_EXPORT MCT_DIR_S *MCT_opendir(const CHAR *pcDirName);

/**  close a directory
* param: pstDir            input the pointer to the open dir stream
* return VOID
*/
MCT_EXPORT VOID MCT_closedir(MCT_DIR_S *pstDir);

/**  read a directory
* param: pstDir       input the pointer to the open dir stream
* return MCT_DIRENT_S * a pointer to a dirent structure. If an error occurs, NULL is returned and errno is set appropriately.
*/
MCT_EXPORT MCT_DIRENT_S *MCT_readdir(MCT_DIR_S *pstDir);

/**  scan a directory for matching entries
* param: pcDirName          input the pointer to the open dir path string
* param: appstDirNamelist  input the pointer to the sub-dir array
* param: pfnSelector         input the pointer to the select dir function
* param: pfnComparator     input the pointer to the sort dir function
* return LONG the number of directory entries selected or -1 if an error occurs.
*/
MCT_EXPORT LONG MCT_scandir(const CHAR *pcDirName,
                              MCT_DIRENT_S **appstDirNamelist[],
                              MCT_SCANDIR_SELECTOR_PF pfnSelector,
                              MCT_SCANDIR_COMPARATOR_PF pfnComparator);

/**  sort  by alphabet
* param: pVala          input the pointer to the compare data a
* param: pValb          input the pointer to the compare data b
* param: pfnSelector         input the pointer to the select dir function
* param: pfnComparator     input the pointer to the sort dir function
* return LONG, 0 :pVala same as pValb
                     >0 : pVala greater than pValb
                     <0 : pVala less than pValb
*/
MCT_EXPORT LONG MCT_alphasort(const VOID *pVala, const VOID *pValb);

/**  delete a directory
* param: pcPath      input the pointer to the delete dir path
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_rmdir(const CHAR *pcPath);

/**  change current work directory
* param: pcPath      input the pointer to the new work dir path
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_chdir(const CHAR *pcPath);

/**  create a socket
* param: lProtoFamily      input the socket family type
* param: lType               input the socket type
* param: lProto               input the socket transport type
* return MCT_HANDLE the socket handle, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT MCT_HANDLE MCT_socket(LONG lProtoFamily, LONG lType, LONG lProto);

/**  bind a socket with address
* param: hHandle      input the socket handle
* param: pstAddr      input the pointer to the bind address
* param: lAddrlen      input the address length
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_bind(MCT_HANDLE hHandle, MCT_SOCKADDR_S *pstAddr, LONG lAddrlen);

/**  connect the socket to the address
* param: hHandle      input the socket handle
* param: pstAddr      input the pointer to the connect address
* param: lAddrlen      input the address length
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_connect(MCT_HANDLE hHandle, MCT_SOCKADDR_S *pstAddr, LONG lAddrlen);

/**  listen the socket
* param: hHandle      input the socket handle
* param: lBacklog      input the max number process connect
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_listen(MCT_HANDLE hHandle, LONG lBacklog);

/**  accept the socket connect
* param: hHandle      input the socket handle
* param: pstAddr      input the pointer to the store remote address
* param: lAddrlen      input the address length
* return MCT_HANDLE the socket handle, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT MCT_HANDLE MCT_accept(MCT_HANDLE hHandle,  MCT_SOCKADDR_S *pstAddr,  LONG *plAddrlen);

/**  receive data from the socket
* param: hHandle      input the socket handle
* param: pcBuf         input the pointer to the store data buffer
* param: ulLen          input the buffer length
* param: lFlags         input the recv option, default is 0
* return LONG the bytes of recv data, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_recv(MCT_HANDLE hHandle, CHAR *pcBuf, SIZE_T ulLen, LONG lFlags);

/**  send data by the socket
* param: hHandle      input the socket handle
* param: pcBuf         input the pointer to the send data buffer
* param: ulLen          input the buffer length
* param: lFlags         input the send option, default is 0
* return LONG the bytes of send data, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_send(MCT_HANDLE hHandle, const CHAR *pcBuf, SIZE_T ulLen, LONG lFlags);

/**  receive data from the socket
* param: hHandle      input the socket handle
* param: pcBuf         input the pointer to the store data buffer
* param: ulLen          input the buffer length
* param: lFlags         input the recv option, default is 0
* param: pstAddr      input the pointer to the store remote address
* param: lAddrlen      input the address length
* return LONG the bytes of recv data, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_recvfrom(MCT_HANDLE hHandle, CHAR *pcBuf, SIZE_T ulLen, LONG lFlags, MCT_SOCKADDR_S *pstAddr, LONG *plAddrlen);

/**  send data to the define address by the socket
* param: hHandle      input the socket handle
* param: pcBuf         input the pointer to the send data buffer
* param: ulLen          input the buffer length
* param: lFlags         input the send option, default is 0
* param: pstAddr      input the pointer to the store remote address
* param: lAddrlen      input the address length
* return LONG the bytes of recv data, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_sendto(MCT_HANDLE hHandle, const CHAR *pcBuf, SIZE_T ulLen, LONG lFlags, const MCT_SOCKADDR_S *pstAddr, LONG lAddrlen);

/**  close socket connect
* param: hHandle      input the socket handle
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_closesocket(MCT_HANDLE hHandle);

/**  shutdown socket
* param: hHandle      input the socket handle
* param: lHow          input the terminate type(such as:read\send\read and send)
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_shutdown(MCT_HANDLE hHandle, LONG lHow);

/**  set socket option
* param: hHandle      input the socket handle
* param: lLevel         input the network layer
* param: lOptname    input the set option name
* param: pcOptval     input the pointer to the set option value
* param: lOptlen       input the set option value length
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_setsockopt(MCT_HANDLE hHandle, LONG lLevel, LONG lOptname, const CHAR *pcOptval, LONG lOptlen);

/**  get socket option
* param: hHandle      input the socket handle
* param: lLevel         input the network layer
* param: lOptname    input the get option name
* param: pcOptval     input the pointer to the store option value
* param: lOptlen       input the get option value length
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_getsockopt(MCT_HANDLE hSockHandle, LONG lLevel, LONG lOptName, CHAR *pcOptVal, LONG *plOptLen);

/**  get host info by name
* param: pcName      input the host name
* return MCT_HOSTENT_S * a pointer to hostent structure or a NULL pointer if an error occurs
*/
MCT_EXPORT MCT_HOSTENT_S *MCT_gethostbyname(const CHAR *pcName);

/**  get host info by address
* param: pcAddr       input the pointer to the address info
* param: lLength       input the address structure length
* param: lType         input the address type
* return MCT_HOSTENT_S * a pointer to hostent structure or a NULL pointer if an error occurs
*/
MCT_EXPORT MCT_HOSTENT_S *MCT_gethostbyaddr(const CHAR *pcAddr, LONG lLength, LONG lType);

/**  get host info by address
* param: hHandle      input the socket handle
* param: pcAddr       input the pointer to the remote address info
* param: plAddrlen    input the pointer to the remote address length
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_getpeername(MCT_HANDLE hHandle,  MCT_SOCKADDR_S *pstAddr,  LONG *plAddrlen);

/**  converts the internet host address from IPv4 numbers-and-dots notation into binary data in network byte order.
* param: pcName      input the pointer to the internet host address
* return ULONG binary data in network byte order, if invalid input then return INADDR_NONE
*/
MCT_EXPORT ULONG MCT_inet_addr(const CHAR *pcName);

/**  converts the internet host address from the IPv4 numbers-and-dots notation into binary form (in network byte order)
* param: pcName      input the pointer to the internet host address
* param: pstInAddr    input the pointer to the store binary form
* return LONG nonzero if the address is valid, zero if not.
*/
MCT_EXPORT LONG MCT_inet_aton(const CHAR *pcName, MCT_IN_ADDR_S *pstInAddr);

/**  converts the binary form (in network byte order) into internet host address from the IPv4 numbers-and-dots notation
* param: pstInAddr    input the pointer to the binary form
* return CHAR * a pointer to the internet host address, if failed return NULL.
*/
MCT_EXPORT CHAR *MCT_inet_ntoa(const MCT_IN_ADDR_S *pstInAddr);

/**  monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation
* param: lWidth        input the MAX fd + 1
* param: pstRfds      input the pointer to the read fds array
* param: pstWfds     input the pointer to the write fds array
* param: pstEfds      input the pointer to the error fds array
* param: lMsec         input the MAX wait time
* return LONG  amount of can proceess fd, if timeout return 0, if error occur return -1.
*/
MCT_EXPORT LONG MCT_select(LONG lWidth, MCT_FD_SET_S *pstRfds, MCT_FD_SET_S *pstWfds, MCT_FD_SET_S *pstEfds, const LONG lMsec);

/**  wait for some event on a file descriptor
* param: pstPollfds   input the set of file descriptors to be monitored is specified in the fds
* param: ulLen         input the amount of file descriptors
* param: lMsec         input the MAX wait time
* return LONG  amount of can proceess fds, if timeout return 0, if error occur return -1.
*/
MCT_EXPORT LONG MCT_poll(MCT_POLLFD_S *pstPollfds, ULONG ulLen, const LONG lMsec);

/**  create thread
* param: pfnFunc         input the pointer to the thread process function
* param: pArgs            input the pointer to the thread process function arg
* param: lFlags            input the create thread option, for linux ,can set MCT_THR_DETACHED attribute
* param: pstThrId        input the pointer to store thread id
* param: lPriority         input the thread priority, use MCT_DEFAULT_THREAD_PRIORITY for default
* param: ppThrName    input the pointer to thread name string
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_thr_create(MCT_THR_FUNC pfnFunc, VOID *pArgs, LONG lFlags, MCT_THREAD_S *pstThrId, LONG lPriority, const CHAR **ppThrName);

/**  force terminate thread
* param: stThrId         input the thread id
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_thr_cancel(MCT_THREAD_S stThrId);

/**  exit thread
* param: stStatus         input the thread exit status
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT VOID MCT_thr_exit(MCT_THR_FUNC_RETURN stStatus);

/**  relist the thread queue
* param: VOID
* return VOID
*/
MCT_EXPORT VOID MCT_thr_yield(VOID);

/**  init the mutex
* param: pstMutex        input the pointer to the mutex
* param: lLockCope       input the lock scope, default is 0
* param: pcName          input the pointer to mutex name, default is NULL
* param: pstMutexAttr   input the mutex attribute, default is NULL
* param: lLockType       input the mutex type, default is 0
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
this mutex support recursion
*/
MCT_EXPORT LONG MCT_mutex_init(MCT_MUTEX_S *pstMutex, LONG lLockCope, const CHAR *pcName, MCT_MUTEXATTR_S *pstMutexAttr, LPSECURITY_ATTRIBUTES stSa, LONG lLockType);

/**  lock the mutex
* param: pstMutex        input the pointer to the mutex
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_mutex_lock(MCT_MUTEX_S *pstMutex);

/**  try to lock the mutex
* param: pstMutex        input the pointer to the mutex
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_mutex_trylock(MCT_MUTEX_S *pstMutex);

/**  unlock the mutex
* param: pstMutex        input the pointer to the mutex
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_mutex_unlock(MCT_MUTEX_S *pstMutex);

/**  destory the mutex
* param: pstMutex        input the pointer to the mutex
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_mutex_destroy(MCT_MUTEX_S *pstMutex);

/**  init the condition
* param: pstCv             input the pointer to the init condition structure
* param: sType             input the condition type, default is 0
* param: pcName          input the pointer to condition name
* param: pArg              input the args, default is NULL
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_cond_init(MCT_COND_S *pstCv, SHORT sType, const CHAR *pcName, VOID *pArg);

/**  set the condition signal
* param: pstCv             input the pointer to the set condition structure
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_cond_signal(MCT_COND_S *pstCv);

/**  wait the condition signal
* param: pstCv             input the pointer to the wait condition structure
* param: pstMutex        input the pointer to the mutex
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_cond_wait(MCT_COND_S *pstCv, MCT_MUTEX_S *pstMutex);

/**  wait the condition signal
* param: pstCv             input the pointer to the wait condition structure
* param: pstMutex        input the pointer to the mutex
* param: pstMutex        input the time to wait, unit is ms
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_cond_timedwait(MCT_COND_S *pstCv, MCT_MUTEX_S *pstMutex,  LONG lMSeconds);

/**  destory the condition signal
* param: pstCv             input the pointer to the destory condition structure
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_cond_destroy(MCT_COND_S *pstCv);

/**  load the dll lib
* param: pcFileName             input the pointer to the dll lib path
* param: lMode                    input the load mode
* return MCT_SHLIB_HANDLE  the dll lib handle, if error occurred return NULL
*/
MCT_EXPORT MCT_SHLIB_HANDLE MCT_dlopen(const CHAR *pcFileName, LONG lMode);

/**  unload the dll lib
* param: hLibHandle             input the the dll lib handle
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_dlclose(MCT_SHLIB_HANDLE hLibHandle);

/**  get function from the dll lib
* param: hLibHandle             input the the dll lib handle
* param: pcSymbol              input the pointer to the function symbol name
* return MCT_LIBMETHOD_PF a pointer to the function address, if error occurred return NULL
*/
MCT_EXPORT MCT_LIBMETHOD_PF MCT_dlsym(MCT_SHLIB_HANDLE hLibHandle, const CHAR *pcSymbol);

/**  get time from 1-1-1970
* param: pstClock             input the pointer to store the seconds from 1-1-1970 00:00:00
* return MCT_TIME_S the seconds from 1-1-1970 00:00:00, if error occurred return -1
*/
MCT_EXPORT MCT_TIME_S MCT_time(MCT_TIME_S *pstClock);

/**  get seconds from computer started
* param: pstClock             input the pointer to store the seconds from computer started
* return MCT_TIME_S the seconds from computer started, if error occurred return -1
*/
MCT_EXPORT MCT_TIME_S MCT_monotonic_time(MCT_TIME_S *pstClock);

/**  converts a broken-down time structure, expressed as local time, to calendar time representation
* param: pstDt             input the pointer to the broken-down time structure
* return MCT_TIME_S the seconds from computer started, if error occurred return -1
note:before use, your need confirm the value of pstDt->lIsDst
*/
MCT_EXPORT MCT_TIME_S MCT_mktime(const MCT_DATE_TIME_S *pstDt);

/**  converts a broken-down time structure, expressed as local time, to calendar time representation
* param: pstDt             input the pointer to the broken-down time structure
* return MCT_TIME_S the seconds from computer started, if error occurred return -1
note:this function will auto adjust value of pstDt->lIsDst
*/
MCT_EXPORT MCT_TIME_S MCT_mktime_withdst(MCT_DATE_TIME_S *pstDt);

/**  get UTC time
* param: pstClock             input the pointer to store the UTC time
* return MCT_DATE_TIME_S
*/
MCT_EXPORT MCT_DATE_TIME_S MCT_gmtime(const MCT_TIME_S *pstClock);

/**  get local time
* param: pstClock             input the pointer to store the local time
* return MCT_DATE_TIME_S
note:not thread safe
*/
MCT_EXPORT MCT_DATE_TIME_S MCT_localtime(const MCT_TIME_S *pstClock);

/**  get local time
* param: pstClock             input the pointer to store the local time
* param: pstRes               input the pointer to store the local time with date-time struction
* return MCT_DATE_TIME_S * a pointer store the local time with date-time struction
*/
MCT_EXPORT MCT_DATE_TIME_S *MCT_localtime_r(const MCT_TIME_S *pstClock, MCT_DATE_TIME_S *pstRes);

/**  formats the broken-down time tm according to the format specification format and places the result in the character array pcBuf of size ulMaxsize
* param: pcBuf                input the pointer to store the output time
* param: ulMaxsize           input the max size of this buffer
* param: pcFormat           input the pointer to the format string
* param: pstDateTime       input the pointer to the source time
* return SIZE_T the active output buffer length
*/
MCT_EXPORT SIZE_T MCT_strftime(CHAR *pcBuf, SIZE_T ulMaxsize, const CHAR *pcFormat, const MCT_DATE_TIME_S *pstDateTime);

/**  formats the broken-down time tm according to the format specification format and places the result in the character array pcBuf of size ulMaxsize
* param: pcBuf                input the pointer to source time
* param: pcFormat           input the pointer to the format string
* param: pstDateTime       input the pointer to store the formated time
* return CHAR * a pointer to the buffer behind format string, if nothing return NULL
*/
MCT_EXPORT CHAR *MCT_strptime(const CHAR *pcBuf, const CHAR *pcFormat, MCT_DATE_TIME_S *pstDateTime);

/**  get time from 1-1-1970 00:00:00
* param: VOID
* return MCT_TIME_VALUE_S time from 1-1-1970 00:00:00
*/
MCT_EXPORT MCT_TIME_VALUE_S MCT_gettimeofday(VOID);

/**  set system time
* param: pstTimeval input the pointer to set time, must UTC time
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
note:windows just support to unit ms
*/
MCT_EXPORT LONG MCT_settimeofday(const MCT_TIME_VALUE_S *pstTimeval);

/**  high-precision sleep
* param: pstSpecReq    input the pointer to need sleep time
* param: pstSpecRem   input the pointer to remainder sleep time
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
note:windows just support to unit ms
*/
MCT_EXPORT LONG MCT_nanosleep(const MCT_TIMESPEC_S *pstSpecReq, MCT_TIMESPEC_S *pstSpecRem);

/**  get environment var value
* param: pcRootName    input the pointer to environment var name
* return CHAR * a pointer to the environment value
note:not thread safe
*/
MCT_EXPORT CHAR *MCT_getenv(const CHAR *pcRootName);

/**  converts the initial portion of the string pointed to by pcValue to number
* param: pcValue    input the pointer to string
* return LONG the converted value
*/
MCT_EXPORT LONG MCT_atol(const CHAR *pcValue);

/**  converts the number to string
* param: lValue       input the need coverted number
* param: pcStr       input the pointer to store the number string
* param: lRadix       input the number type
* return  CHAR* a pointer to the coverted number string
*/
MCT_EXPORT CHAR *MCT_ltoa(LONG lValue,  CHAR *pcStr, LONG lRadix);

/**  converts the initial portion of the string pointed to by pcValue to double-unsigned-long number
* param: pcValue    input the pointer to string
* return DULONG the converted value
*/
MCT_EXPORT DULONG MCT_atodul(const CHAR *pcValue );

/**  converts the number to string
* param: dulValue   input the need coverted double-unsigned-long number
* param: pcStr       input the pointer to store the double-unsigned-long number string
* return  VOID
*/
MCT_EXPORT VOID MCT_dultoa(DULONG dulValue, CHAR *pcStr );

/**  converts the string to number
* param: pcStr        input the pointer to the number string
* param: ppcEndPtr  input the pointer to the last invalid char position, if no char invalid, return NULL
* param: lRadix        input the number type
* return LONG the coverted number
*/
MCT_EXPORT LONG MCT_strtol(const CHAR *pcStr,  CHAR **ppcEndPtr, LONG lRadix);

/**  converts the string to double-long
* param: pcStr        input the pointer to the double-long string
* param: ppcEndPtr  input the pointer to the last invalid char position, if no char invalid, return NULL
* param: lRadix        input the number type
* return DLONG the coverted double-long
*/
MCT_EXPORT DLONG MCT_strtoll(const CHAR *pcStr,  CHAR **ppcEndPtr, LONG lRadix);

/**  init the signal set
* param: pstSigset       input the pointer to the signal set structure
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_sigemptyset(MCT_SIGSET_S *pstSigset);

/**  check and set the signal action
* param: lSignum       input the signal number
* param: pstNsa        input the pointer to the new signal action, can be NULL
* param: pstOsa        input the pointer to the store old signal action
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_sigaction(LONG lSignum, const MCT_SIGACTION_S *pstNsa,  MCT_SIGACTION_S *pstOsa);

/**  get current process id
* param: VOID
* return MCT_PID_S current process id
*/
MCT_EXPORT MCT_PID_S MCT_getpid(VOID);

/**  wait and get process status
* param: stPid              input the pid of wait process,
   for linux:
   stpid == 0, wait any process in the same group with current process
   stpid == -1, wait any sub-process of current process
   stpid < -1, wait any process which group id match -stpid
* param: pstStatus       input the pointer to store the process status
* param: lOption           input the wait option, default is 0
   for windows: just MCT_WNOHANG valid, means not block
   for linux: support MCT_WNOHANG\MCT_WUNTRACED\MCT_WCONTINUED
* return MCT_PID_S exit process id, if error occurred return -1
   for linux: if lOption is MCT_WNOHANG and the pid not valid current, return 0
*/
MCT_EXPORT MCT_PID_S MCT_waitpid(MCT_PID_S stPid,  MCT_EXITCODE_S *pstStatus, LONG lOption);

/**  exit the process
* param: lStatus       input the process exit status
* return VOID
*/
MCT_EXPORT VOID MCT_exit(LONG lStatus);

/**  create a pseudo-random integer in the range 0 to RAND_MAX
* param: VOID
* return LONG return the create random integer
*/
MCT_EXPORT LONG MCT_rand(VOID);

/**  create a pseudo-random integer in the range 0 to RAND_MAX by seed
* param: ulSeed       input the rand seed
* return LONG return the create random integer
*/
MCT_EXPORT LONG MCT_rand_r(ULONG ulSeed);

/**  sleep with seconds
* param: ulSeconds       input the sleep seconds
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_sleep(ULONG ulSeconds);

/**  sleep with milli-seconds
* param: lMSeconds       input the sleep milli-seconds
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_msleep(LONG lMSeconds);

/**  manipulates the underlying device parameters of special files
* param: hHandle       input the device description
* param: lCmd           input the system operate command
* param: pVal            input the system operate command parameters
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_ioctl(MCT_HANDLE hHandle, LONG lCmd, VOID *pVal);

/**  converts the unsigned integer hostlong from host byte order to network byte order.
* param: ulHost         input the unsigned integer hostlong
* return LONG network byte order of hostlong.
*/
MCT_EXPORT ULONG MCT_htonl(ULONG ulHost);

/**  converts the unsigned integer hostlong from network byte order to host byte order.
* param: ulHost         input the unsigned integer hostlong with network byte order
* return LONG host byte order of hostlong.
*/
MCT_EXPORT ULONG MCT_ntohl(ULONG ulNetwork);

/**  converts the unsigned short hostlong from host byte order to network byte order.
* param: ulHost         input the unsigned short hostlong
* return LONG network byte order of hostlong.
*/
MCT_EXPORT USHORT MCT_htons(USHORT usHost);

/**  converts the unsigned short hostlong from network byte order to host byte order.
* param: ulHost         input the unsigned short hostlong with network byte order
* return LONG host byte order of hostlong.
*/
MCT_EXPORT USHORT MCT_ntohs(USHORT usNetwork);

/**  converts the unsigned double-long hostlong from host byte order to network byte order.
* param: ulHost         input the unsigned double-long hostlong
* return DULONG network byte order of hostlong.
*/
MCT_EXPORT DULONG MCT_htonll(DULONG dulValue);

/**  converts the unsigned double-long hostlong from network byte order to host byte order.
* param: ulHost         input the unsigned double-long hostlong with network byte order
* return DULONG host byte order of hostlong.
*/
MCT_EXPORT DULONG MCT_ntohll(DULONG dulValue);

/**  judge system is network byte order.
* param: VOID
* return BOOL_T BOOL_TRUE means the system is  network byte order
*/
MCT_EXPORT BOOL_T MCT_IsBigEndian(VOID);

/**  get system network card MAC.
* param: ulMaxLen     input the length of store MAC buffer, must greater than 12
* param: pcMacStr    input the pointer to the store MAC buffer
* return LONG the active MAC string length, if error occurred return 0.
*/
MCT_EXPORT ULONG MCT_getmac(ULONG ulMaxLen,  CHAR *pcMacStr);

/**  checks for an alphanumeric character
* param: cChar         input the need check character
* return LONG for alphanumeric character return non-zero, otherwise return zero.
*/
MCT_EXPORT LONG MCT_isalnum(CHAR cChar);

/**  checks for an alpha character
* param: cChar         input the need check character
* return LONG for alpha character return non-zero, otherwise return zero.
*/
MCT_EXPORT LONG MCT_isalpha(CHAR cChar);

/**  checks process is running
* param: pcName         input the pointer to the flag of need check process
* return BOOL_T for process running return BOOL_TRUE, else not running
*/
MCT_EXPORT BOOL_T MCT_check_running(const CHAR *pcName);

/**  wait for thread
* param: stWaiterThrId  input the wait destination thread id
* param: pstThrId         input the pointer to store return thread id, can be NULL
* param: pstStatus       input the pointer to store thread status
* param: lPriority         input the thread priority, use MCT_DEFAULT_THREAD_PRIORITY for default
* param: ppThrName    input the pointer to thread name string
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_thr_join(MCT_THREAD_S stWaiterThrId,  MCT_THREAD_S *pstThrId,  ACE_THR_FUNC_RETURN *pstStatus);

/**  retrieve the time of the specified clock clk_id.
* param: stClockId        input the clock clk_id
* param: pstTimeSpec   input the point to the retrieve time
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
note: MCT_CLOCKID_S support type:MCT_CLOCK_REALTIME\MCT_CLOCK_MONOTONIC\MCT_CLOCK_PROCESS_CPUTIME_ID\MCT_CLOCK_THREAD_CPUTIME_ID
*/
MCT_EXPORT LONG MCT_clock_gettime(MCT_CLOCKID_S stClockId, MCT_TIMESPEC_S *pstTimeSpec);

/**  converts the MCT_TIME_S time to local string date time
* param: pstTm        input the time
* param: szBuf         input the point to the store transform date time
* param: lBuflen        input the buf length
* return CHAR * the tranform date string point
*/
MCT_EXPORT CHAR * MCT_ctime_r(const MCT_TIME_S *pstTm, CHAR *szBuf, LONG lBuflen);

/**  create a pipe
* param: hHandles        input the point to store pipe handle
                                 hHandles[0] for read, hHandles[1] for write
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_pipe(MCT_HANDLE hHandles[]);

/**  set signal action function
* param: lSigNum                  input the signal number
* param: pfSignalHandler        input the pointer to the signal action function
* return MCT_SIGNAL_HANDLER_PF a pointer to the signal action function, if error occurred return -1
*/
MCT_EXPORT MCT_SIGNAL_HANDLER_PF MCT_signal_set(LONG lSigNum, MCT_SIGNAL_HANDLER_PF pfSignalHandler);

/**  judge the file whether end
* param: pFile        input the handle of file
* return LONG if to the file end return non-zero, if error occurred return zero
*/
MCT_EXPORT LONG MCT_feof(FILE *pFile);

/**  clean file stream error flag
* param: pFile        input the handle of file
* return VOID
*/
MCT_EXPORT VOID MCT_clearerr(FILE *pFile);

/**  format input for file stream
* param: pFile           input the handle of file
* param: pcFormat     input the pointer to the format
* return LONG the input argu numbers, if error occurred return -1
*/
MCT_EXPORT LONG MCT_fscanf(FILE *pFile, const CHAR *pcFormat, ...);

/**  check file stream is occurred error
* param: pFile        input the handle of file
* return LONG if error occurred return non-zero
*/
MCT_EXPORT LONG MCT_ferror(FILE *pFile);

/**  get link file content
* param: pcPath        input the pointer to the link file path
* param: pcBuf          input the pointer to store file content
* param: ulBufSize      input the file content length
* return LONG the active get file content length, if error occurred return -1
*/
MCT_EXPORT LONG MCT_readlink(const CHAR *pcPath, CHAR *pcBuf, ULONG ulBufSize);

/**  get the system error number
* param: VOID
* return LONG the system last error code
*/
MCT_EXPORT LONG MCT_getlasterr(VOID);

/**  set the system error number
* param: lErrorCode         input the set error code
* return VOID
*/
MCT_EXPORT VOID MCT_setlasterr(LONG lErrorCode);

/**  get socket local address info
* param: hHandle         input the handle of socket
* param: pstAddr         input the pointer of store the address info
* param: plAddrlen       input the length of the address info
* return LONG 0 is succeed. Otherwise, -1 is returned and errno is set to indicate the error.
*/
MCT_EXPORT LONG MCT_getsockname(MCT_HANDLE hHandle,  MCT_SOCKADDR_S *pstAddr,  LONG *plAddrlen);

/**  zip a file
* param: pcZipFile        input the point to need zip file path
* param: pcExDir          input the point to destination path
* return LONG
for linux:
if succeed return the shell command exit value
if call /bin/sh failed, return 127, other failed returned is -1 and exit code of the command will be WEXITSTATUS(status)
if pcStr is NULL, return non-zero
note:if pcExDir is NULL, zip to current work path; if exist then covered it
*/
MCT_EXPORT LONG MCT_unzip(const CHAR *pcZipFile, const CHAR *pcExDir);

/**  detached thread
* param: stThrId         input the thread id
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_thr_detach(MCT_THREAD_S stThrId);

/**  set the thread priority
* param: lInc input need addition nice value
* return LONG the value of new nice
*/
MCT_EXPORT LONG MCT_nice(LONG lInc);

/**  set file privilege umask
* param: stMask        input the privilege umask, value between(0x000~0x777)
* return MCT_MODE_S if no error occurred return set value
*/
MCT_EXPORT MCT_MODE_S MCT_umask(MCT_MODE_S stMask);

/**  change file mode bit
* param: pcPath      input the pointer to the file or dir path
* param: lMode        input the privilege type
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_chmod(const CHAR *pcPath, MCT_MODE_S lMode);

/** below API just support linux */
#ifndef WIN32

/**  set file description
* param: hHandle       input the file description
* param: lCmd           input the system operate command
* param: pVal            input the system operate command parameters
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
if lCmd is F_DUPFD, return a new file description
if lCmd is F_GETFD, return non negative number
if lCmd is F_SETFD, return -1 for error occurred and set errno to indicate the error.
if lCmd is F_GETFL, return non negative number
if lCmd is F_SETFL, return -1 for error occurred and set errno to indicate the error.
if lCmd is F_GETLK, return -1 for error occurred and set errno to indicate the error.
if lCmd is F_SETLK, return -1 for error occurred and set errno to indicate the error.
if lCmd is F_SETLKW, return -1 for error occurred and set errno to indicate the error.
if lCmd is F_GETOWN, return -1 for error occurred and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_fcntl(MCT_HANDLE hFHandle, LONG lCmd, LONG lArg);

/**  create a process
* param: pProgramName  the process name, can be NULL
* return LONG , if error occurred return -1 and set errno to indicate the error.
otherwise 0 for sub-process, greater than 0 for parent process
*/
MCT_EXPORT MCT_PID_S MCT_fork(const CHAR *pProgramName);

/**  open pipe stream to or from a process
* param: pcCommand      input the need execute command
* param: pcMode            input the pointer to the pipe mode
* return FILE * pointer to the pipe, if failed return NULL and set errno to indicate the error.
*/
MCT_EXPORT FILE *MCT_popen(const CHAR *pcCommand, const CHAR *pcMode);

/**  close pipe stream
* param: pStream      input the pointer to the pipe
* return LONG return the command exit code, if failed return -1 and set errno to indicate the error.
note: use with MCT_popen()
*/
MCT_EXPORT LONG MCT_pclose(FILE *pStream);

#endif

/**  get system name info
* param: pstName      input the pointer to store Name info
* return LONG 0 is success, if failed return -1 and set errno to indicate the error.
*/
MCT_EXPORT LONG MCT_uname (MCT_UTSNAME_S *pstName);


#ifdef  __cplusplus
}
#endif /* end of __cplusplus */

#endif /* _MCT_SYSTEM_H_ */
